package com.cskaoyan.javase.network._1udp._v1;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

/**
 * 接收端
 *
 * 注意事项:
 *      1.UDP是无连接的,谁先启动都无所谓.当然为了确保接收端能够接收数据,要先启动接收端
 *      2.(重点)接收端的receive方法是一个阻塞方法,它会持续监听一个端口号,等待发送端发送数据
 *          只有接收到数据,接收端才会继续运行
 *
 * @since 10:48
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Receiver2 {
    public static void main(String[] args) throws IOException {
        // 接收端的思路是什么?
        // 1.创建接收端套接字对象,DatagramSocket对象,必须明确指出ip地址和端口号
        // 这里给出的端口号,意思是监听这个端口号,如果该端口号下有数据报包传输来,则进行接收
        /*
            这个端口号和发送端有没有关系呢?
            发送端和数据报包就是将数据发送到码头
            所以发送端的数据报包中的ip地址端口号
            和接收端的"码头"套接字对象 ip地址端口号
            保持一致
         */
        DatagramSocket receiverSocket = new DatagramSocket(8888);

        // 2.创建一个新的byte数组,用于接收数据报包封装的字节数据
        byte[] buf = new byte[1024];
        DatagramPacket receiverPacket = new DatagramPacket(buf, buf.length);
        // 接收端的数据报包只关心接收数据,不关心数据来源,所以它的构造器不需要IP地址和端口号
        // 构造 DatagramPacket，用来接收长度为length的包，在缓冲区中指定了偏移量。
        // DatagramPacket(byte[] buf, int offset, int length)
        // 构造 DatagramPacket，用来接收长度为length的数据包。
        // DatagramPacket(byte[] buf, int length)
        // 3.用DatagramSocket对象的成员方法-receive方法,接收数据报包
        receiverSocket.receive(receiverPacket);

        // 4.解包,解析出发送端发送的数据
        // 依赖于DatagramPacket的成员方法
        // 返回数据缓冲区，即数据包封装的字节数据
        // byte[] getData()
        byte[] msgBytes = receiverPacket.getData();
        // 返回将要发送或接收到的数据的长度。
        // int getLength()
        int length = receiverPacket.getLength();
        // // 返回将要发送或接收到的数据的偏移量。
        // int getOffset()
        int offset = receiverPacket.getOffset();
        String msg = new String(msgBytes, offset, length);

        // 获取数据包（要发送到的或者发送者）的IP地址
        // InetAddress getAddress()
        // 获取数据包（要发送到的或者发送者）的端口号
        // int getPort()
        // 获取数据包（要发送到的或者发送者）的IP地址和端口号
        // SocketAddress getSocketAddress()
        System.out.println("来自于:" + receiverPacket.getSocketAddress() + ",他发送的消息是:" + msg);
        // 5.close关闭资源
        receiverSocket.close();
    }
}
